<?php

/**
 * Requests to budgetpulse.com and returns info
 *
 * @author Petrica
 */
class HttpService {
  
  protected $baseUrl;
  protected $loginUrl;
  protected $tagsUrl;
  protected $categoriesUrl;
  protected $accountsUrl;
  protected $transactionsAddUrl;
  
  /**
   *
   * @var sfWebBrowser
   */
  protected $client;
  
  public function __construct() {
    $this->baseUrl = sfConfig::get('app_http_service_base_url', null);
    
    $loginUrl = sfConfig::get('app_http_service_login_url', null);
    if ($loginUrl) {
      $this->loginUrl = $this->baseUrl . $loginUrl;
    }
    
    $tagsUrl = sfConfig::get('app_http_service_tags_url', null);
    if ($tagsUrl) {
      $this->tagsUrl = $this->baseUrl . $tagsUrl;
    }
    
    $dashboardUrl = sfConfig::get('app_http_service_dashboard_url', null);
    if ($dashboardUrl) {
      $this->dashboardUrl = $this->baseUrl . $dashboardUrl;
    }
    
    $categoriesUrl = sfConfig::get('app_http_service_categories_url', null);
    if ($dashboardUrl) {
      $this->categoriesUrl = $this->baseUrl . $categoriesUrl;
    }
    
    $accountsUrl = sfConfig::get('app_http_service_accounts_url', null);
    if ($accountsUrl) {
      $this->accountsUrl = $this->baseUrl . $accountsUrl;
    }
    
    $transactionsAddUrl = sfConfig::get('app_http_service_transactions_add_url', null);
    if ($transactionsAddUrl) {
      $this->transactionsAddUrl = $this->baseUrl . $transactionsAddUrl;
    }
    
    $this->initClient();
  }
  
  /**
   * Initialize client browser
   */
  protected function initClient() {
    $this->client = new sfWebBrowser(array(), 'sfCurlAdapter', array('cookies' => true, 'ssl_verify' => false));
  }
  
  /**
   * Login to budgetpulse
   * 
   * @param type $username
   * @param type $password 
   */
  public function login($username, $password) {
    
    $this->client->post($this->loginUrl, array('data[User][email]' => $username, 'data[User][password]' => $password));
    if ($this->client->getResponseCode() == '200') {
      $url = $this->client->getUrlInfo();
      $info = parse_url($this->dashboardUrl);
      
      if ($url['path'] == $info['path']) {
        return true;
      }
    }
    else {
      throw new HttpException("Bad response.");
    }
    
    return false;
  }
  
  /**
   * Get tags
   */
  public function getTags() {
    $this->client->post($this->tagsUrl);
    if ($this->client->getResponseCode() == '200') {
      $url = $this->client->getUrlInfo();
      $info = parse_url($this->loginUrl);
      
      if ($url['path'] != $info['path']) {
        
        $response = $this->client->getResponseDomCssSelector();
        
        $domTags = $response->matchAll('#tag_form span.tagEdit');
        
        $tags = array();
        if (count($domTags)) {
          foreach($domTags as $domTag) {
            $name = trim($domTag->nodeValue);
            $id = $domTag->getAttribute('id');
            $ids = explode('_', $id);
            $id = (int)$ids[1];
            
            $tags[] = array(
              'name' => $name,
              'id' => $id
            );
          }
        }
        
        return $tags;
      }
    }
    else {
      throw new HttpException("Bad response.");
    }
    
    return false;
  }
  
  public function getCategories() {
    $this->client->post($this->categoriesUrl);
    if ($this->client->getResponseCode() == '200') {
      $url = $this->client->getUrlInfo();
      $info = parse_url($this->loginUrl);
      
      if ($url['path'] != $info['path']) {
        
        $response = $this->client->getResponseDomCssSelector();
        
        $domCategories = $response->matchAll('#transaction_category_form .categoryEdit');
        
        $categories = array();
        if (count($domCategories)) {
          foreach($domCategories as $domCategory) {
            $name = trim($domCategory->nodeValue);
            $id = $domCategory->getAttribute('id');
            $ids = explode('_', $id);
            $id = (int)$ids[1];
            
            $categories[] = array(
              'name' => $name,
              'id' => $id
            );
          }
        }
        
        return $categories;
      }
    }
    else {
      throw new HttpException("Bad response.");
    }
    
    return false;
  }
  
  public function getAccounts() {
    $this->client->post($this->accountsUrl);
    if ($this->client->getResponseCode() == '200') {
      $url = $this->client->getUrlInfo();
      $info = parse_url($this->loginUrl);
      
      if ($url['path'] != $info['path']) {
        $accounts = array();
        
        $response = $this->client->getResponseDomCssSelector();
        
        $domTrs = $response->matchAll('#manage_accounts tr');
        
        foreach($domTrs as $k => $domTr) {
          if ($domTr->getAttribute('class') != 'extra') {
            $domTds = $domTr->getElementsByTagName('td');
            
            if ($domTds->length > 2) {
              $domSpans = $domTds->item(1)->getElementsByTagName('span');
              
              if ($domSpans->length == 1) {
                $domSpan = $domSpans->item(0);
                
                $name = trim($domSpan->nodeValue);
                $id = $domSpan->getAttribute('id');
                $ids = explode('-', $id);
                $id = (int)$ids[2];
              }
              
              $accounts[] = array(
                'name' => $name,
                'id' => $id
              );
            }
          }
        }
        
        return $accounts;
      }
    }
    else {
      throw new HttpException("Bad response.");
    }
    
    return false;
  }
  
  /**
   * Add a new transaction
   * 
   * @param string $type - Expense | Income
   * @param integer $accountId
   * @param string $description
   * @param DateTime $date
   * @param double $amount
   * @param string $category
   * @param array $tags - string array
   */
  public function addTransaction($type, $accountId, $description, $date, $amount, $category, $tags) {
    
    $category = array_merge(array($category), $tags);
    
    $params = array(
      'data[Transaction][transaction_type]' => $type,
      'data[Transaction][account_id]' => $accountId,
      'data[Transaction][description]' => $description,
      'data[Transaction][transaction_date]' => $date->format('m/d/Y'),
      'data[Transaction][amount]' => $amount,
      'data[TransactionCategory][name]' => implode(',', $category)
    );
    
    $this->client->post($this->transactionsAddUrl, $params);
    if ($this->client->getResponseCode() == '200') {
      $url = $this->client->getUrlInfo();
      $info = parse_url($this->loginUrl);
      
      if ($url['path'] != $info['path']) {
        $response = json_decode($this->client->getResponseText());
        if ($response->success) {
          return true;
        }
      }
    }
    else {
      throw new HttpException("Bad response.");
    }
    
    return false;
  }
  
}

?>
